import { cloneDeep } from 'lodash-es'
import BaseGlobalSetting from '@/diy/globalSetting/BaseGlobalSetting'
import { getPxValue, getUUID, setPxValue } from '@/utils'
import type { IDiyBase } from '@/diy/types'
import { nextTick } from 'vue'
import { generateCode, htmlInsertHeader, saveAsFile } from '@/utils/helper'
import Moveable from 'moveable'

interface IPreviewData {
  globalSetting: BaseGlobalSetting
  pageData: IDiyBase[]
}

interface IGuidelines {
  horizontalGuidelines: number[]
  verticalGuidelines: number[]
}

interface ICanvasControl {
  update: () => void
  debounceUpdate: () => void
  getMoveable: () => Moveable
}

export class DiyStore {
  /**
   * 画布id，一般可用于获取画布html代码/生成图片
   */
  canvasId = 'diy-preview'
  /**
   * 一般用于获取拖动画布的控制器
   */
  dragZoneId = 'diy-preview-zone'
  /**
   * 当前激活的组件
   */
  currentComponent: IDiyBase | null = null

  /**
   * 预览的数据
   */
  previewData: IPreviewData = {
    globalSetting: new BaseGlobalSetting(),
    pageData: []
  }

  /**
   * 辅助线
   */
  guidelines: IGuidelines = {
    horizontalGuidelines: [],
    verticalGuidelines: []
  }

  //是否显示网格背景
  showGrid: boolean = true

  /**
   * 是否处于编辑状态
   */
  isEdit: boolean = true

  /**
   * 是否全屏
   */
  isFullscreen: boolean = false

  /**
   * 画布控制器
   */
  canvasControl: ICanvasControl | null = null
  setCanvasControl(_canvasControl: ICanvasControl) {
    this.canvasControl = cloneDeep(_canvasControl)
  }

  /**
   * 设置当前激活组件
   * @param data
   */
  setCurComponent(data: IDiyBase | null) {
    if (data) {
      this.currentComponent = cloneDeep(data)
    } else {
      this.currentComponent = null
    }
  }

  /**
   * 添加组件
   * @param origin
   */
  addComponent(origin: IDiyBase) {
    const clone = cloneDeep(origin)
    clone.id = 'id' + getUUID()
    this.previewData.pageData.push(clone)
    this.currentComponent = clone
  }

  /**
   * 复制组件
   */
  copyComponent(origin: IDiyBase) {
    const copyItem: IDiyBase = cloneDeep(origin)
    const { left, top } = copyItem.style
    //偏移10像素
    copyItem.style.left = setPxValue(getPxValue(left) + 10)
    copyItem.style.top = setPxValue(getPxValue(top) + 10)
    this.addComponent(copyItem)
  }

  /**
   * 删除组件
   */
  deleteComponent(id: string) {
    const index = this.previewData.pageData.findIndex((el) => el.id === id)
    this.previewData.pageData.splice(index, 1)
    this.setCurComponent(null)
  }

  /**
   * 清除当前组件和预览的数据
   */
  clearComponent() {
    this.currentComponent = null
    this.previewData.pageData = []
  }

  /**
   * 更新预览数据
   * @param data
   */
  updatePreviewData(data: IPreviewData) {
    this.previewData = cloneDeep(data)
  }

  /**
   * 获取html代码
   * @param needHeader 是否需要插入html头部信息
   * @param variableList 变量列表，用于将变量替换成预览的模板值
   */
  getHtmlCode(needHeader = false, variableList: any[] = []) {
    return new Promise<string>((resolve) => {
      this.isEdit = false
      nextTick(() => {
        const domId = this.canvasId
        const tempCode = generateCode(domId, variableList)
        const code = needHeader ? htmlInsertHeader(tempCode) : tempCode
        resolve(code)
        this.isEdit = true
      })
    })
  }

  /**
   * 导出为html文件
   */
  async exportAsHtmlFile(needHeader = false, fileName: string) {
    if (!fileName) {
      fileName = `证书模板-${Date.now()}.html`
    }
    const code = await this.getHtmlCode(needHeader)
    saveAsFile(code, fileName)
  }
}
